﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;

namespace xCarLinkMP3Organizer
{
    class UsbDrives : IDisposable
	{
		private UsbDriveStateMonitor _window;

        public UsbDrives()
        {
            _window = new UsbDriveStateMonitor();
        }

        public event EventHandler<UsbStateChangedEventArgs> StateChanged
        {
            add { _window.StateChanged += value; }
            remove { _window.StateChanged -= value; }
        }

        public List<UsbDrive> GetAvailable()
        {
            return (
                       from ManagementObject drive in
                           new ManagementObjectSearcher(
                           "select DeviceID, Model from Win32_DiskDrive where InterfaceType='USB'").Get()
                       let partition =
                           new ManagementObjectSearcher(
                           String.Format(
                               "associators of {{Win32_DiskDrive.DeviceID='{0}'}} where AssocClass = Win32_DiskDriveToDiskPartition",
                               drive["DeviceID"])).First()
                       where partition != null
                       let logical =
                           new ManagementObjectSearcher(
                           String.Format(
                               "associators of {{Win32_DiskPartition.DeviceID='{0}'}} where AssocClass = Win32_LogicalDiskToPartition",
                               partition["DeviceID"])).First()
                       where logical != null
                       let volume =
                           new ManagementObjectSearcher(
                           String.Format("select FreeSpace, Size, VolumeName from Win32_LogicalDisk where Name='{0}'",
                                         logical["Name"])).First()
                       select new UsbDrive(logical["Name"].ToString())
                                  {
                                      Model = drive["Model"].ToString(),
                                      Volume = volume["VolumeName"].ToString(),
                                      FreeSpace = (ulong) volume["FreeSpace"],
                                      Size = (ulong) volume["Size"]
                                  }).ToList();
        }

        public void UpdateInfo(UsbDrive disk)
		{
			var partition = new ManagementObjectSearcher(String.Format(
				"associators of {{Win32_LogicalDisk.DeviceID='{0}'}} where AssocClass = Win32_LogicalDiskToPartition",
				disk.Name)).First();

		    if (partition == null) return;

		    var drive = new ManagementObjectSearcher(String.Format(
		        "associators of {{Win32_DiskPartition.DeviceID='{0}'}}  where resultClass = Win32_DiskDrive",
		        partition["DeviceID"])).First();

		    if (drive != null)
		        disk.Model = drive["Model"].ToString();

		    var volume = new ManagementObjectSearcher(
		        String.Format(
		            "select FreeSpace, Size, VolumeName from Win32_LogicalDisk where Name='{0}'",
		            disk.Name))
		        .First();

		    if (volume != null)
		    {
		        disk.Volume = volume["VolumeName"].ToString();
		        disk.FreeSpace = (ulong)volume["FreeSpace"];
		        disk.Size = (ulong)volume["Size"];
		    }
		}

        public void Dispose()
        {
            if (_window != null)
            {
                _window.Dispose();
                _window = null;
            }
        }
	}

    public static class WmiExtensions
    {
        public static ManagementObject First(this ManagementObjectSearcher mos)
        {
            return mos.Get().Cast<ManagementObject>().FirstOrDefault();
        }
    }
}
